package org.web.standardplatform.client.builder;

import freemarker.template.Template;
import freemarker.template.TemplateException;

import org.web.standardplatform.client.domain.buildproject.*;
import org.web.standardplatform.client.helper.BuilderHelper;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;


/***
 * build base project, it 's  parent project of the all project.
 * It builds directory、pom.xml， it obey spring project standard. */
public class MainBuildProjectBuilder implements ProjectDefinitionConstant {

    public static void main(String[] args) {
        ProjectDefinitionDO projectDefinitionDO = new ProjectDefinitionDO();
        projectDefinitionDO.setVersion("1.0.0");
        projectDefinitionDO.setGroupId("org.web");
        projectDefinitionDO.setArtifactId("web-display");
        projectDefinitionDO.setOutputPath("D://output4");
        projectDefinitionDO.init();
        projectDefinitionDO.getParentProjectDefinitionDO().setJavaVersion("21");

        try {
            buildParentProject(projectDefinitionDO);
            buildSDKProject(projectDefinitionDO);
            buildServerProject(projectDefinitionDO);
            buildStaterProject(projectDefinitionDO);
            buildClientDemoProject(projectDefinitionDO);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println();
    }


    public static void buildParentProject(ProjectDefinitionDO projectDefinitionDO) throws IOException, TemplateException {
        File projectDirectory = BuilderHelper.getProjectOutputDirectory(projectDefinitionDO);
        projectDirectory.deleteOnExit();
        mkdir(projectDirectory);

        // 构建父工程的pom.xml
        String parentProjectDirectory = projectDirectory.getAbsolutePath();
        Writer out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(parentProjectDirectory + File.separator + "pom.xml")), StandardCharsets.UTF_8));
        Template template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "parent-PomXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建父工程的readme.md
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(parentProjectDirectory + File.separator + "README.md")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "parent-readme.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建父工程的 .gitignore
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(parentProjectDirectory + File.separator + ".gitignore")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "parent-gitignore.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();
    }

    public static void buildSDKProject(ProjectDefinitionDO projectDefinitionDO) throws Exception {
        ClientProjectDefinitionDO clientProjectDefinitionDO = projectDefinitionDO.getClientProjectDefinitionDO();

        // 构建Parent工程文件夹
        File projectDirectory = BuilderHelper.getProjectOutputDirectory(projectDefinitionDO);
        projectDirectory = new File(projectDirectory.getAbsoluteFile() + File.separator + clientProjectDefinitionDO.getClientProjectName());
        projectDirectory.deleteOnExit();
        mkdir(projectDirectory);
        //mkdir(Paths.get(projectDirectory.getAbsolutePath() + File.separator + clientProjectDefinitionDO.getSuffix().replace("-", "")).toFile());

        // client父工程的pom.xml
        String parentProjectDirectory = projectDirectory.getAbsolutePath();
        Writer out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(parentProjectDirectory + File.separator + "pom.xml")), StandardCharsets.UTF_8));
        Template template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "client-PomXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建src/main
        String basePath = parentProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.main.java", projectDefinitionDO).toLowerCase();
        if (basePath.contains("\\server\\")){
            basePath = basePath.replaceFirst("\\\\server\\\\", "\\\\");
        }
        File file = Paths.get(basePath + File.separator + clientProjectDefinitionDO.getSuffix().replaceAll("-", "").toLowerCase()).toFile();
        String startClassFile = file.getAbsolutePath();
        mkdir(file);
        buildClientDirectory(file.getAbsolutePath());

        // 构建java类。
        // 构建样例DTO类
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "dto" + File.separator + "AccountInfoDTO.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "client-demo-DTO.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建样例Query类
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "dto" + File.separator + "query" + File.separator + "QueryAccountInfoRequest.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "client-demo-QueryRequest.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建样例Biz 接口类
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "biz" + File.separator + "AccountInfoBiz.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "client-demo-Biz.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建src/test
        //file = Paths.get(basePath + File.separator + BuilderHelper.transferLine2Humps(clientProjectDefinitionDO.getClientProjectName(), HALF_WAY_LINE, false).toLowerCase()).toFile();
        //mkdir(file);

        // 构建src/main/resources
        basePath = parentProjectDirectory + File.separator + BuilderHelper.transferString2Path("src.main.resources");
        file = Paths.get(basePath).toFile();
        mkdir(file);
    }

    public static void buildClientDemoProject(ProjectDefinitionDO projectDefinitionDO) throws Exception {
        ClientDemoProjectDefinitionDO clientDemoProjectDefinitionDO = projectDefinitionDO.getClientDemoProjectDefinitionDO();
        projectDefinitionDO.getServerProjectDefinitionDO().setProjectDefinitionDO(projectDefinitionDO);

        // 构建demo工程文件夹
        File projectDirectory = BuilderHelper.getProjectOutputDirectory(projectDefinitionDO);
        projectDirectory = new File(projectDirectory.getAbsoluteFile() + File.separator + clientDemoProjectDefinitionDO.getClientDemoProjectName());
        projectDirectory.deleteOnExit();
        mkdir(projectDirectory);


        // server 父工程的pom.xml
        String serverProjectDirectory = projectDirectory.getAbsolutePath();
        Writer out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(serverProjectDirectory + File.separator + "pom.xml")), StandardCharsets.UTF_8));
        Template template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "demo-PomXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();


        // 构建src/main/java
        String basePath = serverProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.main.java", projectDefinitionDO).toLowerCase();
        File file = Paths.get(basePath + File.separator + projectDefinitionDO.getClientDemoProjectDefinitionDO().getSuffix().replaceAll("-", "").toLowerCase()).toFile();
        String startClassFile = file.getAbsolutePath();
        mkdir(file);

        buildDemoDirectory(file.getAbsolutePath());

        // 构建启动类，spring-boot 启动类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + clientDemoProjectDefinitionDO.getDemoProjectStartClassName() + ".java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "demo-StartApplicationJava.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建Controller 样例类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "controller" + File.separator + "DemoHelloWorldController.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "demo-DemoHelloWorldController.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建 config java.
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "config" + File.separator + "DemoConfig.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "demo-config.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建src/test
        basePath = serverProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.test.java", projectDefinitionDO).toLowerCase();
        file = Paths.get(basePath + File.separator + clientDemoProjectDefinitionDO.getSuffix().replaceAll("-", "")).toFile();
        mkdir(file);

        basePath = file.getAbsolutePath();
        file = Paths.get(basePath + File.separator + "config").toFile();
        mkdir(file);


        // 构建src/main/resources
        basePath = serverProjectDirectory + File.separator + BuilderHelper.transferString2Path("src.main.resources");
        file = Paths.get(basePath).toFile();
        mkdir(file);

        // 构建application.properties
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "application.yml")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "demo-ApplicationYml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建log4j2.xml。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "log4j2-spring.xml")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "demo-Log4j2SpringXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

    }

    public static void buildStaterProject(ProjectDefinitionDO projectDefinitionDO) throws Exception {
        projectDefinitionDO.getServerProjectDefinitionDO().setProjectDefinitionDO(projectDefinitionDO);
        ServerProjectDefinitionDO serverProjectDefinitionDO = projectDefinitionDO.getServerProjectDefinitionDO();

        // 构建stater工程文件夹
        File projectDirectory = BuilderHelper.getProjectOutputDirectory(projectDefinitionDO);
        projectDirectory = new File(projectDirectory.getAbsoluteFile() + File.separator +projectDefinitionDO.getArtifactId()+"-starter" );
        projectDirectory.deleteOnExit();
        mkdir(projectDirectory);

        // stater 父工程的pom.xml
        String starterProjectDirectory = projectDirectory.getAbsolutePath();
        Writer out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(starterProjectDirectory + File.separator + "pom.xml")), StandardCharsets.UTF_8));
        Template template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "starter-PomXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建 src/java
        String basePath = starterProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.main.java", projectDefinitionDO).toLowerCase();
        basePath = starterProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.main.java", projectDefinitionDO).toLowerCase();
        File file = Paths.get(basePath).toFile();
        mkdir(file);
        file = Paths.get(basePath + File.separator + "starter").toFile();
        mkdir(file);

        // mkdir starter springboot java.
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "starter-springboot.ftl");
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + projectDefinitionDO.getStarterProjectDefinitionDO().getStarterSpringBootName()+".java")), StandardCharsets.UTF_8));
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建src/main/resources
        basePath = starterProjectDirectory + File.separator + BuilderHelper.transferString2Path("src.main.resources");
        file = Paths.get(basePath).toFile();
        mkdir(file);
        // 构建src/main/resources/META-INF
        file = Paths.get(file.getAbsolutePath() + File.separator + "META-INF").toFile();
        mkdir(file);
        // 构建src/main/resources/META-INF/spring.factories
        if (projectDefinitionDO.getParentProjectDefinitionDO().getJavaVersion().equals("1.8") || projectDefinitionDO.getParentProjectDefinitionDO().getJavaVersion().equals("8")) {
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "spring.factories")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "starter-spring-factories.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
        } else {
            mkdir(Paths.get(file.getAbsolutePath() +File.separator+"spring").toFile());
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "spring"+File.separator+"org.springframework.boot.autoconfigure.AutoConfiguration.imports")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "starter-spring-factories-springboot3.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
        }
        out.close();
    }



    public static void buildServerProject(ProjectDefinitionDO projectDefinitionDO) throws Exception {
        projectDefinitionDO.getServerProjectDefinitionDO().setProjectDefinitionDO(projectDefinitionDO);
        ServerProjectDefinitionDO serverProjectDefinitionDO = projectDefinitionDO.getServerProjectDefinitionDO();

        // 构建Server工程文件夹
        File projectDirectory = BuilderHelper.getProjectOutputDirectory(projectDefinitionDO);
        projectDirectory = new File(projectDirectory.getAbsoluteFile() + File.separator + serverProjectDefinitionDO.getServerProjectName());
        projectDirectory.deleteOnExit();
        mkdir(projectDirectory);


        // server 工程的pom.xml
        String serverProjectDirectory = projectDirectory.getAbsolutePath();
        Writer out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(serverProjectDirectory + File.separator + "pom.xml")), StandardCharsets.UTF_8));
        Template template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-PomXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();


        //server 工程的 docker-deploy
        if (projectDefinitionDO.getServerProjectDefinitionDO().getHasDocker()) {
            serverProjectDirectory = projectDirectory.getAbsolutePath();
            File dockerDeployFolder = new File(serverProjectDirectory + File.separator + "docker-deploy");
            if (!dockerDeployFolder.exists()) {
                dockerDeployFolder.mkdir();
            }
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(dockerDeployFolder.getAbsolutePath() + File.separator + "build.sh")), StandardCharsets.UTF_8));
            String dockerDeployTemplateFolder = "docker-deploy";
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()) + File.separator + dockerDeployTemplateFolder, "build.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
            out.close();
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(dockerDeployFolder.getAbsolutePath() + File.separator + "dockerfile")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()) + File.separator + dockerDeployTemplateFolder, "dockerfile.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
            out.close();
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(dockerDeployFolder.getAbsolutePath() + File.separator + "entrypoint.sh")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()) + File.separator + dockerDeployTemplateFolder, "entrypoint.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
            out.close();
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(dockerDeployFolder.getAbsolutePath() + File.separator + "run.sh")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()) + File.separator + dockerDeployTemplateFolder, "run.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
            out.close();
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(dockerDeployFolder.getAbsolutePath() + File.separator + "trigger-build.sh")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()) + File.separator + dockerDeployTemplateFolder, "trigger-build.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
            out.close();
            out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(dockerDeployFolder.getAbsolutePath() + File.separator + "trigger-run.sh")), StandardCharsets.UTF_8));
            template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()) + File.separator + dockerDeployTemplateFolder, "trigger-run.ftl");
            BuilderHelper.process(template, out, projectDefinitionDO);
            out.close();
        }


        // 构建src/main/java
        String basePath = serverProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.main.java", projectDefinitionDO).toLowerCase();
        File file = Paths.get(basePath + File.separator + projectDefinitionDO.getServerProjectDefinitionDO().getSuffix().replaceAll("-", "").toLowerCase()).toFile();
        String startClassFile = file.getAbsolutePath();
        mkdir(file);

        buildServerDirectory(file.getAbsolutePath());

        // 构建启动类，spring-boot 启动类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + serverProjectDefinitionDO.getServerProjectStartClassName() + ".java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-StartApplicationJava.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 添加样例Domain
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "domain" + File.separator + "AccountInfoDO.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-domain.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "domain" + File.separator + "query" + File.separator + "QueryAccountInfo.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-query.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "dao" + File.separator + "AccountInfoDAO.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-dao.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "service" + File.separator + "AccountInfoService.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-service.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "biz" + File.separator + "impl" + File.separator + "AccountInfoBizImpl.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-biz-impl.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建Controller 样例类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "controller" + File.separator + "HelloWorldController.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-HelloWorldController.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建Controller 样例类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "controller" + File.separator + "ExcelController.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-ExcelController.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "controller" + File.separator + "AccountInfoController.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-AccountInfoController.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();


        // 构建Config 样例类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "config" + File.separator + serverProjectDefinitionDO.getServerProjectClassName() + "Config.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-ConfigJava.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();
        // 构建Datasource Config 样例类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator  + "config"+ File.separator +serverProjectDefinitionDO.getServerProjectClassName()+ "DBConfig.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-db-configJava.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建Json-Config 样例类。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(startClassFile + File.separator + "config" + File.separator  + "JacksonConfig.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-config-for-json.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建src/test
        basePath = serverProjectDirectory + File.separator + BuilderHelper.javaProjectBaseDirectory("src.test.java", projectDefinitionDO).toLowerCase();
        file = Paths.get(basePath + File.separator + serverProjectDefinitionDO.getSuffix().replaceAll("-", "")).toFile();
        mkdir(file);

        basePath = file.getAbsolutePath();
        file = Paths.get(basePath + File.separator + "config").toFile();
        mkdir(file);
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "TestParseConfig.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-TestParseConfig.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "Config1.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-Config1.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "UserConfig.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-UserConfig.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 添加测试类，校验controller 开发URI的正确性。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "TestParseRequestMapping.java")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-TestParseRequestMapping.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建src/main/resources
        basePath = serverProjectDirectory + File.separator + BuilderHelper.transferString2Path("src.main.resources");
        file = Paths.get(basePath).toFile();
        mkdir(file);

        // 构建application.properties
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "application.yml")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-ApplicationYml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建log4j2.xml。
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "log4j2-spring.xml")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-Log4j2SpringXml.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

        // 构建访问数据Mapper
        file = Paths.get(file.getAbsolutePath() + File.separator + "mapper").toFile();
        mkdir(file);
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "mybatis-config-all.xml")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-MapperPropertiesXML.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);

        // 构建一个样例SQL建表语句
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "db.sql")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-sql.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);

        // 添加一个样例文件,统一放置到
        file = Paths.get(file.getAbsolutePath() + File.separator + projectDefinitionDO.getServerProjectDefinitionDO().getServerProjectClassName()).toFile();
        mkdir(file);
        out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(file.getAbsolutePath() + File.separator + "Mapper_account_info.xml")), StandardCharsets.UTF_8));
        template = BuilderHelper.getTemplate(BuilderHelper.getProjectTemplatePath(projectDefinitionDO.getTemplatePath()), "server-demo-mybatis.ftl");
        BuilderHelper.process(template, out, projectDefinitionDO);
        out.close();

    }


    public static void mkdir(File file) {
        file.mkdirs();
    }

    public static void buildClientDirectory(String basePath) {
        if (basePath.endsWith(".server")){
            basePath = basePath.substring(0, basePath.length()-6);
        }
        // 构建src/main/java, groupId/serverProjectName/sdk/biz
        File file = Paths.get(basePath + File.separator + "biz").toFile();
        mkdir(file);
        // 构建src/main/java, groupId/serverProjectName/sdk/dto
        file = Paths.get(basePath + File.separator + "dto").toFile();
        mkdir(file);
        // 构建src/main/java, groupId/serverProjectName/sdk/dto/query
        file = Paths.get(basePath + File.separator + "dto" + File.separator + "query").toFile();
        mkdir(file);
    }

    public static void buildDemoDirectory(String basePath) {
        // 构建src/main/java, groupId/serverProjectName/controller
        File file = Paths.get(basePath + File.separator + "controller").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/service
        file = Paths.get(basePath + File.separator + "service").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/config
        file = Paths.get(basePath + File.separator + "config").toFile();
        mkdir(file);

    }

    public static void buildServerDirectory(String basePath) {
        // 构建src/main/java, groupId/serverProjectName/controller
        File file = Paths.get(basePath + File.separator + "controller").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/service
        file = Paths.get(basePath + File.separator + "service").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/dao
        file = Paths.get(basePath + File.separator + "dao").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/domain
        file = Paths.get(basePath + File.separator + "domain").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/domain
        file = Paths.get(basePath + File.separator + "domain" + File.separator + "query").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/config
        file = Paths.get(basePath + File.separator + "config").toFile();
        mkdir(file);

        // 构建src/main/java, groupId/serverProjectName/biz
        file = Paths.get(basePath + File.separator + "biz"+File.separator+"impl").toFile();
        mkdir(file);
    }
}
